package model

import (
	"background/db"
	"strings"
	"ubntgo/logger"

	json "github.com/json-iterator/go"
	"github.com/olivere/elastic/v7"
	"qiniupkg.com/x/log.v7"
)

type Field struct {
	Field string `sql:"Field"`
	Type  string `sql:"Type"`
	Key   string `sql:"Key"`
}

func MysqlToElasticSearchMapping(types string, Key string) string {
	if Key == "PRI" {
		return "long"
	}
	if strings.Contains(types, "int(") {
		return "long"
	}
	if strings.Contains(types, "longblob") {
		return "text"
	}
	if strings.Contains(types, "varchar") {
		return "text"
	}
	if strings.Contains(types, "datetime") {
		return "date"
	}
	if strings.Contains(types, "blob") {
		return "text"
	}
	return ""
}

/*
"settings":{
		"number_of_shards":1,
		"number_of_replicas":0
	},
	"mappings":{
		"properties":{
			"user":{
				"type":"keyword"
			},
			"message":{
				"type":"text",
				"store": true,
				"fielddata": true
			},
			"tags":{
				"type":"keyword"
			},
			"location":{
				"type":"geo_point"
			},
			"suggest_field":{
				"type":"completion"
			}
		}
	}
*/
// 不同类型db之间进行缓存
func QueryDocument(query elastic.Query, limit int, offset int) ([]Hardware, error) {
	var ret []Hardware
	ids, e := db.GetElastic().Query("doc", query, ret, limit, offset)
	if nil != e {
		return nil, e
	}
	i := 0
	for _, v := range ids {
		ret[i].ID = v
		i++
	}
	return ret, nil
}
func InsertDocToElaticSearch(doc DocTree) error {
	matchPhraseQuery := elastic.NewTermQuery("title.keyword", doc.Title)
	existedHardware, e := QueryDoc(matchPhraseQuery, 10, 0)
	if nil != e {
		log.Print(e.Error())
		return e
	}
	if len(existedHardware) == 0 {
		log.Print("doc created ", doc.Title)
		e = db.GetElastic().Create("doc", "0", "", doc)
		if nil != e {
			log.Print(e.Error())
			return e
		}
		return nil
	} else {
		log.Print("doc existed ", doc.Title)

	}
	return nil
}
func InsertCrawDocToElaticSearch(doc DocTree) error {
	matchPhraseQuery := elastic.NewTermQuery("title.keyword", doc.Title)
	existedHardware, e := QueryDoc(matchPhraseQuery, 10, 0)
	if nil != e {
		log.Print(e.Error())
		return e
	}
	if len(existedHardware) == 0 {
		log.Print("doc created ", doc.Title)
		e = db.GetElastic().Create("doc", "0", "", doc)
		if nil != e {
			log.Print(e.Error())
			return e
		}
		return nil
	} else {
		log.Print("doc existed ", doc.Title)

	}
	return nil
}
func CreateIndexFromMysqlTable(tblname string) error {
	columns := []Field{}
	e := db.GetMysqlClient().Query2("describe "+tblname, &columns)
	if nil != e {
		logger.Debug(e.Error())
		return e
	}
	if existed, _ := db.GetElastic().IndexExisted(tblname); existed {
		log.Print("index not existed , create " + tblname)
	} else {
		props := map[string]interface{}{}
		mapping := map[string]interface{}{
			"settings": map[string]interface{}{
				"analysis": map[string]interface{}{
					"analyzer": map[string]interface{}{
						"default": map[string]interface{}{
							"type": "smartcn",
						},
					},
				},
			},
			"mappings": map[string]interface{}{
				"properties": props,
			},
		}
		for _, v := range columns {
			props[v.Field] = map[string]string{"type": MysqlToElasticSearchMapping(v.Type, v.Key)}
		}
		dat, e := json.Marshal(mapping)
		if nil != e {
			log.Print(e.Error())
		}
		e = db.GetElastic().CreateIndex(tblname, string(dat))
		if nil != e {
			log.Print(e.Error())
		}
		log.Print(string(dat))

	}
	return nil
}

func PortDocumentToElasticsearch(tblname string, indexname string) error {
	ret, e := GetAllDocs(tblname)
	if nil != e {
		log.Print(e.Error())
	}
	columns := []Field{}
	e = db.GetMysqlClient().Query2("describe "+tblname, &columns)
	if nil != e {
		logger.Debug(e.Error())
		return e
	}
	if existed, _ := db.GetElastic().IndexExisted(indexname); !existed {
		props := map[string]interface{}{}
		mapping := map[string]interface{}{
			"settings": map[string]interface{}{
				"analysis": map[string]interface{}{
					"analyzer": map[string]interface{}{
						"default": map[string]interface{}{
							"type": "ik_smart",
							// "type": "smartcn",
						},
					},
				},
			},
			"mappings": map[string]interface{}{
				"properties": props,
			},
		}

		for _, v := range columns {
			props[v.Field] = map[string]interface{}{"type": MysqlToElasticSearchMapping(v.Type, v.Key)}
			if MysqlToElasticSearchMapping(v.Type, v.Key) == "text" {
				props[v.Field].(map[string]interface{})["fields"] = map[string]interface{}{
					"keyword": map[string]interface{}{
						"type": "keyword",
					},
				}
			}

		}

		dat, e := json.Marshal(mapping)
		if nil != e {
			log.Print(e.Error())
		}
		log.Print(string(dat))
		e = db.GetElastic().CreateIndex(indexname, string(dat))
		if nil != e {
			log.Print(e.Error())
		}
		log.Print(string(dat))
		for _, v := range ret {
			e := InsertCrawDocToElaticSearch(v)
			if nil != e {
				log.Print(e.Error())
			}
		}
	} else {
		for _, v := range ret {
			e := InsertCrawDocToElaticSearch(v)
			if nil != e {
				log.Print(e.Error())
			}
		}
	}
	return nil
}
